package com.aw.baselib.util

import android.content.Context
import android.os.Build
import android.os.Environment
import android.util.Log
import com.aw.baselib.base.AwBaseApplication
import com.aw.baselib.util.AwDataUtil.getIntValue
import com.aw.baselib.util.AwDataUtil.isEmpty
import com.aw.baselib.util.AwDateUtil.formatDate
import com.aw.baselib.util.AwDateUtil.getSpecDate
import com.aw.baselib.util.AwFileUtil.deleteFile
import java.io.File
import java.io.FileInputStream
import java.io.FileWriter
import java.io.IOException
import java.net.HttpURLConnection
import java.net.URL
import java.text.DecimalFormat
import java.util.Calendar
import java.util.Date

/**
 * @author : hzw
 * @date : 2021/4/1
 */
class AwLogFileUtil {
    fun setDebug(isDebug: Boolean): AwLogFileUtil {
        mIsDebug = isDebug
        return this
    }

    fun setFilePrefix(filePreFix: String): AwLogFileUtil {
        mFilePrefix = filePreFix
        return this
    }

    private fun showLog(str: String) {
        if (!mIsDebug) {
            return
        }
        Log.d(TAG, str)
    }

    fun setContext(context: Context?): AwLogFileUtil {
        mContext = context
        filePath_log = fileUrl
        return this
    }

    fun setMaxFileSize(fileSize: Double): AwLogFileUtil {
        mMaxFileSize = fileSize
        return this
    }

    private val allFileList: List<String?>
        private get() {
            val dateStr = formatDate(
                getSpecDate(System.currentTimeMillis(), Calendar.DAY_OF_YEAR, -3),
                AwDateUtil.FORMAT_YMD2
            )
            val list: MutableList<String?> = ArrayList()
            val file = File(
                mContext!!.getExternalFilesDir("")!!.absolutePath
            )
            val files = file.listFiles()
            for (i in files.indices) { // 遍历目录下所有的文件
                if (files[i].name.contains(mFilePrefix)) {
                    showLog("DelPreDaysRecord Local record file: " + files[i].name)
                    writeFile("DelPreDaysRecord Local record file: " + files[i].name)
                    if (getIntValue(
                            files[i].name.split("_".toRegex()).dropLastWhile { it.isEmpty() }
                                .toTypedArray()[0]) <= getIntValue(dateStr)
                    ) {
                        list.add(files[i].absolutePath)
                    }
                }
            }
            //        createTestRecordFile();
            return list
        }

    fun delPreDaysRecord(): AwLogFileUtil {
        val list = allFileList
        if (!isEmpty(list)) {
            for (temp in list) {
                val file = File(temp)
                deleteFile(file)
                showLog("DelPreDaysRecord records...file: " + file.name)
                writeFile("DelPreDaysRecord records...file: " + file.name)
            }
        } else {
            showLog("DelPreDaysRecord records...empty")
            writeFile("DelPreDaysRecord records...empty")
        }
        return this
    }

    private fun createTestRecordFile() {
        for (i in -10 until -6) {
            val dateStr = formatDate(
                getSpecDate(System.currentTimeMillis(), Calendar.DAY_OF_YEAR, i),
                AwDateUtil.FORMAT_YMD2
            ) + mFilePrefix + ".txt"
            createFile(
                mContext!!.getExternalFilesDir("")!!.absolutePath + "/" + dateStr
            )
        }
    }

    private fun createFile(filepath: String) {
        try {
            val f = File(filepath)
            if (!f.exists()) {
                f.createNewFile()
            }
        } catch (e: IOException) {
            e.printStackTrace()
        }
    }

    private val fileUrl: String
        private get() {
            val dateStr = formatDate(Date(System.currentTimeMillis()), AwDateUtil.FORMAT_YMD2)
            return mContext!!.getExternalFilesDir("")!!.absolutePath + "/" + dateStr + mFilePrefix + ".txt"
        }
    val defaultInfoStr: String
        get() = "手机型号" + AwSystemUtil.systemModel + "; 系统版本:" + Build.VERSION.SDK_INT + "; APP版本: " + AwBaseApplication.instance?.let {
            AwVersionUtil.getVersion(
                it
            )
        }

    fun writeDefault(isMain: Boolean) {
        if (isMain) {
            writeFile("Main." + defaultInfoStr)
        } else {
            writeFile(defaultInfoStr)
        }
    }

    fun writeFile(str: String) {
        if (isEmpty(filePath_log)) {
            showLog("writeFile isEmpty filePath_log")
            return
        }
        var writer: FileWriter? = null
        try {
            val f = File(filePath_log)
            if (!f.exists()) {
                f.createNewFile()
                writeDefault(false)
            }
            val fileSize = getFileOrFilesSize(filePath_log, SIZETYPE_MB)
            showLog("writeFile fileSize: $fileSize")
            if (fileSize > mMaxFileSize) {
                showLog("fileSize > mMaxFileSize to delete...")
                f.delete()
                f.createNewFile()
                writeFile("Exceeding the size..." + mMaxFileSize + " MB,delete old data, create new file")
                writeDefault(false)
            }
            showLog("writeFile str: $str")
            val dateStr = formatDate(Date(System.currentTimeMillis()), "HH:mm:ss")
            writer = FileWriter(f, true)
            writer.write("【$dateStr】 $str\n")
            writer.flush()
        } catch (e: Exception) {
            e.printStackTrace()
            showLog("writeFile Exception: " + e.message)
        } finally {
            try {
                writer!!.close()
            } catch (e: Exception) {
                e.printStackTrace()
                showLog("writeFile close Exception: " + e.message)
            }
        }
    }

    private fun getFileOrFilesSize(filePath: String, sizeType: Int): Double {
        val file = File(filePath)
        var blockSize: Long = 0
        try {
            blockSize = if (file.isDirectory) {
                getFileSizes(file)
            } else {
                getFileSize(file)
            }
        } catch (e: Exception) {
            e.printStackTrace()
            showLog("获取文件大小失败!")
        }
        return FormetFileSize(blockSize, sizeType)
    }

    /**
     * 获取指定文件大小
     *
     * @throws Exception
     */
    @Throws(Exception::class)
    private fun getFileSize(file: File): Long {
        var size: Long = 0
        if (file.exists()) {
            val fis = FileInputStream(file)
            size = fis.available().toLong()
        } else {
            file.createNewFile()
            showLog("获取文件大小, 文件不存在!")
        }
        return size
    }

    /**
     * 获取下载 URL 的文件的大小
     */
    private fun getFileSize(address: String): Long {
        var filesize: Long = 0
        var urlConn: HttpURLConnection? = null
        try {
            val url = URL(address)
            urlConn = url.openConnection() as HttpURLConnection
            urlConn.connectTimeout = 10000
            urlConn!!.readTimeout = 10000
            urlConn.connect()
            filesize = urlConn.contentLength.toLong()
        } catch (e: Exception) {
            e.printStackTrace()
        } finally {
            urlConn!!.disconnect()
        }
        return filesize
    }

    /**
     * 获取指定文件夹(目录)大小
     *
     * @param f
     * @return
     * @throws Exception
     */
    @Throws(Exception::class)
    private fun getFileSizes(f: File): Long {
        var size: Long = 0
        val flist = f.listFiles()
        for (i in flist.indices) {
            size = if (flist[i].isDirectory) {
                size + getFileSizes(flist[i])
            } else {
                size + getFileSize(flist[i])
            }
        }
        return size
    }

    /**
     * 转换文件大小
     *
     * @param fileS
     * @return
     */
    private fun FormetFileSize(fileS: Long): String {
        val df = DecimalFormat("#.00")
        var fileSizeString = ""
        val wrongSize = "0B"
        if (fileS == 0L) {
            return wrongSize
        }
        fileSizeString = if (fileS < 1024) {
            df.format(fileS.toDouble()) + "B"
        } else if (fileS < 1048576) {
            df.format(fileS.toDouble() / 1024) + "KB"
        } else if (fileS < 1073741824) {
            df.format(fileS.toDouble() / 1048576) + "MB"
        } else {
            df.format(fileS.toDouble() / 1073741824) + "GB"
        }
        return fileSizeString
    }

    /**
     * 转换文件大小,指定转换的类型
     *
     * @param fileS
     * @param sizeType
     * @return
     */
    private fun FormetFileSize(fileS: Long, sizeType: Int): Double {
        val df = DecimalFormat("#.00")
        var fileSizeLong = 0.0
        when (sizeType) {
            SIZETYPE_B -> fileSizeLong = java.lang.Double.valueOf(df.format(fileS.toDouble()))
            SIZETYPE_KB -> fileSizeLong =
                java.lang.Double.valueOf(df.format(fileS.toDouble() / 1024))

            SIZETYPE_MB -> fileSizeLong =
                java.lang.Double.valueOf(df.format(fileS.toDouble() / 1048576))

            SIZETYPE_GB -> fileSizeLong = java.lang.Double.valueOf(
                df
                    .format(fileS.toDouble() / 1073741824)
            )

            else -> {}
        }
        return fileSizeLong
    }

    companion object {
        private const val TAG = "AwLogFile"
        val instance: AwLogFileUtil? = null
            get() = field ?: AwLogFileUtil()
        private var mContext: Context? = null
        const val SIZETYPE_B = 1
        const val SIZETYPE_KB = 2
        const val SIZETYPE_MB = 3
        const val SIZETYPE_GB = 4
        private var filePath_log = ""
        private var mFilePrefix = "_aw"
        private var mMaxFileSize = 5.0
        private var mIsDebug = false
        private val localFilePath: String
            private get() = if (Environment.getExternalStorageState() == "mounted") {
                Environment.getExternalStorageDirectory().toString()
            } else {
                Environment.getDownloadCacheDirectory().toString()
            }
    }
}